package org.yaac.server.egql.evaluator.function;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;

import org.yaac.server.egql.evaluator.EvaluationResult;
import org.yaac.server.egql.exception.EGQLException;
import org.yaac.server.egql.processor.ProcessData.ProcessDataRecord;
import org.yaac.shared.ErrorCode;

/**
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
public class DatetimeFunction extends Function {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public void validate() throws EGQLException {
		FunctionUtil.ensureParamSize(ops, 1, 2);
	}

	@Override
	public EvaluationResult evaluate(ProcessDataRecord record) {
		// default formats
		List<String> defaultFormats = Arrays.asList("yyyyMMdd", "yyyyMMddHHmmss");
		
		if (this.ops.isEmpty()) {
			return new EvaluationResult(null).withWarning(ErrorCode.W119);
		} else if (this.ops.size() == 1) {
			EvaluationResult r = ops.get(0).evaluate(record);
			
			if (r.getPayload() instanceof String) {
				String str = (String) r.getPayload();
				for (String defaultFormat : defaultFormats) {
					if (str.length() == defaultFormat.length()) {
						try {
							return new EvaluationResult(
									new SimpleDateFormat(defaultFormat).parse(str), r);
						} catch (ParseException e) {
							// simply ignore parsing if failed
						}
					}
				}
				
				// non of them are successful, return error message
				return r.withWarning(ErrorCode.W116);
			} else {
				return r.withWarning(ErrorCode.W117);
			}
		} else if (this.ops.size() == 2) {
			EvaluationResult r = ops.get(0).evaluate(record);
			EvaluationResult formatR = ops.get(1).evaluate(record);
			
			if (r.getPayload() instanceof String && formatR.getPayload() instanceof String) {
				String str = (String) r.getPayload();
				String formatStr = (String) formatR.getPayload();
				
				try {
					return new EvaluationResult(
							new SimpleDateFormat(formatStr).parse(str), r, formatR);
				} catch (ParseException e) {
					// simply ignore parsing if failed
					return r.withWarning(ErrorCode.W118);
				}
			} else {
				return r.withWarning(ErrorCode.W117);
			}
		} else {
			return ops.get(0).evaluate(record).withWarning(ErrorCode.W119);
		} 
	}

}
